package com.meichis.yndms.component;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.CameraUpdateFactory;
import com.amap.api.maps2d.LocationSource;
import com.amap.api.maps2d.MapView;
import com.amap.api.maps2d.model.*;
import com.meichis.mcsappframework.utils.ScreenUtil;
import com.meichis.mcsappframework.utils.UniversalInterface;
import com.meichis.yndms.R;

/**
 * Created by chenhaifei on 2016/8/4.
 */
public class LocationView extends MapView implements LocationSource,
        AMapLocationListener {
    private OnLocationChangedListener mListener;
    private AMap aMap;
    private AMapLocationClient mlocationClient;
    private AMapLocationClientOption mLocationOption;
    private boolean IsRealtimeShowlocation = true;
    private UniversalInterface locationChangedListener;
    private Marker realtimeMarker;
    private int locationcount = 0;
    private int locationbuttonclick = 0;

    private TextView tv_remark;
    private SparseArray<Marker> markers;

    public LocationView(Context context) {
        super(context);
    }

    public LocationView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
    }

    public LocationView(Context context, AttributeSet attributeSet, int i) {
        super(context, attributeSet, i);
    }

    public void setOnLocationChangedListener(UniversalInterface<Void, AMapLocation> listener) {
        locationChangedListener = listener;
    }

    private void addRemark(Context context) {
        RelativeLayout layout = new RelativeLayout(context);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        layout.setLayoutParams(layoutParams);
        layout.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
        tv_remark = new TextView(context);
        tv_remark.setTextColor(Color.RED);
        tv_remark.setBackgroundResource(R.color.yellow);
        tv_remark.getBackground().setAlpha(150);
        tv_remark.setGravity(Gravity.CENTER_HORIZONTAL);
        int px5 = ScreenUtil.dip2px(5);
        tv_remark.setPadding(px5, px5, px5, px5);
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lp.setMargins(0, 0, 0, 20);

        layout.addView(tv_remark, lp);
        this.addView(layout);
    }

    private void addTopRemark(Context context) {
        RelativeLayout layout = new RelativeLayout(context);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        layout.setLayoutParams(layoutParams);
        layout.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
        tv_remark = new TextView(context);
        tv_remark.setTextColor(Color.RED);
        tv_remark.setBackgroundResource(R.color.yellow);
        tv_remark.getBackground().setAlpha(150);
        tv_remark.setGravity(Gravity.CENTER_HORIZONTAL);
        int px5 = ScreenUtil.dip2px(5);
        tv_remark.setPadding(px5, px5, px5, px5);
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lp.setMargins(0, 0, 0, 20);

        layout.addView(tv_remark, lp);
        this.addView(layout);
    }

    public void setRemark(Context context, String remark) {
        if (tv_remark == null) {
            addRemark(context);
        }
        tv_remark.setText(remark);
    }

    /**
     * 设置一些amap的属性
     */
    public void setUpMap(Bundle savedInstanceState) {
        onCreate(savedInstanceState);
        if (aMap == null) {
            aMap = getMap();
            MyLocationStyle myLocationStyle = new MyLocationStyle();
            // 设置小蓝点的图标
            myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.location_marker));
            // 设置圆形的边框颜色
            myLocationStyle.strokeColor(Color.TRANSPARENT);
            // 设置圆形的填充颜色
            myLocationStyle.radiusFillColor(Color.TRANSPARENT);
            // 设置圆形的边框粗细
            myLocationStyle.strokeWidth(1.0f);
            aMap.setMyLocationStyle(myLocationStyle);
            // 设置定位监听
            aMap.setLocationSource(this);
            // 设置默认定位按钮是否显示
            aMap.getUiSettings().setMyLocationButtonEnabled(true);
            // 设置为true表示显示定位层并可触发定位，false表示隐藏定位层并不可触发定位，默认是false
            aMap.setMyLocationEnabled(true);

            aMap.moveCamera(CameraUpdateFactory.zoomTo(15));
        }
    }

    public void setLocationStyle() {
        if (aMap == null) {
            aMap = getMap();
        }
        MyLocationStyle myLocationStyle = new MyLocationStyle();
        // 设置小蓝点的图标
        myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.location_marker));
        // 设置圆形的边框颜色
        myLocationStyle.strokeColor(Color.TRANSPARENT);
        // 设置圆形的填充颜色
        myLocationStyle.radiusFillColor(Color.TRANSPARENT);
        // 设置圆形的边框粗细
        myLocationStyle.strokeWidth(1.0f);
        aMap.setMyLocationStyle(myLocationStyle);
    }

    public void setMarkerClickListener(AMap.OnMarkerClickListener listener) {
        aMap.setOnMarkerClickListener(listener);
    }

    public void setInfoWindowClickListener(AMap.OnInfoWindowClickListener listener, AMap.InfoWindowAdapter adapter) {
        aMap.setOnInfoWindowClickListener(listener);
        aMap.setInfoWindowAdapter(adapter);
    }

    /**
     * 添加默认格式的Marer
     *
     * @param latitude
     * @param longitude
     * @param defaultMarker
     */
    public void addMarker(double latitude, double longitude, float defaultMarker) {
        if (aMap == null) {
            aMap = getMap();
        }
        aMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(new LatLng(latitude, longitude)).zIndex(1)
                .draggable(true).icon(BitmapDescriptorFactory.defaultMarker(defaultMarker == 0 ? BitmapDescriptorFactory.HUE_RED : defaultMarker)));
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));
    }

    public void addMarker(double latitude, double longitude, float defaultMarker, int key) {
        if (aMap == null) {
            aMap = getMap();
        }
        if (markers == null) {
            markers = new SparseArray<>();
        }
        markers.append(key, aMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(new LatLng(latitude, longitude)).zIndex(1)
                .draggable(true).icon(BitmapDescriptorFactory.defaultMarker(defaultMarker == 0 ? BitmapDescriptorFactory.HUE_RED : defaultMarker))));
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));
    }

    public void addMarker(double latitude, double longitude, float defaultMarker, String title, String snippet) {
        if (aMap == null) {
            aMap = getMap();
        }
        aMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(new LatLng(latitude, longitude)).title(title).draggable(true).snippet(snippet).zIndex(1)
                .icon(BitmapDescriptorFactory.defaultMarker(defaultMarker == 0 ? BitmapDescriptorFactory.HUE_RED : defaultMarker)));
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));
    }

    public void addMarker(double latitude, double longitude, Bitmap bitmap, String title, String snippet) {
        if (aMap == null) {
            aMap = getMap();
        }
        aMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(new LatLng(latitude, longitude)).title(title).draggable(true).snippet(snippet).zIndex(1)
                .icon(BitmapDescriptorFactory.fromBitmap(bitmap)));
    }

    public void moveCamera(double latitude, double longitude) {
        if (aMap == null) {
            aMap = getMap();
        }
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));
    }

    /**
     * 设置是否实时显示当前定位位置
     *
     * @param b
     */
    public void setRealtimeShowlocation(boolean b) {
        IsRealtimeShowlocation = b;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int measureWidth = measureWidth(widthMeasureSpec);
        int measureHeight = measureHeight(heightMeasureSpec);
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measureWidth, measureHeight);
    }

    private int measureWidth(int pWidthMeasureSpec) {
        int result = 0;
        // 得到模式
        int widthMode = View.MeasureSpec.getMode(pWidthMeasureSpec);
        // 得到尺寸
        int widthSize = View.MeasureSpec.getSize(pWidthMeasureSpec);

        switch (widthMode) {
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.EXACTLY:
                result = widthSize;
                break;
            default:
        }
        return result;
    }

    private int measureHeight(int pHeightMeasureSpec) {
        int result = 0;

        int heightMode = View.MeasureSpec.getMode(pHeightMeasureSpec);
        int heightSize = View.MeasureSpec.getSize(pHeightMeasureSpec);

        switch (heightMode) {
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.EXACTLY:
                result = heightSize;
                break;
            default:
        }
        return result;
    }

    @Override
    public void onLocationChanged(AMapLocation amapLocation) {
        if (mListener != null && amapLocation != null) {
            if (amapLocation.getErrorCode() == 0) {
                locationcount++;
                if (IsRealtimeShowlocation) {
                    if (realtimeMarker != null) {
                        realtimeMarker.destroy();
                    }
                    // 显示系统小蓝点
                    mListener.onLocationChanged(amapLocation);
                } else {
                    if (realtimeMarker != null) {
                        realtimeMarker.destroy();
                    }
                    MarkerOptions mmarkerOptions = new MarkerOptions().anchor(0.5f, 0.5f).position(new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude()))
                            .icon(BitmapDescriptorFactory.fromResource(R.mipmap.location_marker));
                    realtimeMarker = aMap.addMarker(mmarkerOptions);
                }
                if (locationChangedListener != null && amapLocation.getAccuracy() < 100 || locationcount >= 2) {
                    locationChangedListener.todo(amapLocation);
                }
                if (locationcount < 2)
                    aMap.moveCamera(CameraUpdateFactory.zoomTo(15));
            }
        }

    }

    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        locationcount = 0;
        locationbuttonclick++;
        if (locationbuttonclick > 1) {
            IsRealtimeShowlocation = true;
        }
        mListener = onLocationChangedListener;
        if (mlocationClient == null) {
            mlocationClient = new AMapLocationClient(this.getContext());
            mLocationOption = new AMapLocationClientOption();
            //设置定位监听
            mlocationClient.setLocationListener(this);
            //设置定位模式为高精度模式，Battery_Saving为低功耗模式，Device_Sensors是仅设备模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //设置是否返回地址信息（默认返回地址信息）
            mLocationOption.setNeedAddress(true);
            //设置是否只定位一次,默认为false
            mLocationOption.setOnceLocation(false);
            if (mLocationOption.isOnceLocationLatest()) {
                mLocationOption.setOnceLocationLatest(true);
                //设置setOnceLocationLatest(boolean b)接口为true，启动定位时SDK会返回最近3s内精度最高的一次定位结果。
                //如果设置其为true，setOnceLocation(boolean b)接口也会被设置为true，反之不会。
            }
            //设置是否强制刷新WIFI，默认为强制刷新
            mLocationOption.setWifiActiveScan(true);
            //设置是否允许模拟位置,默认为false，不允许模拟位置
            mLocationOption.setMockEnable(false);
            //设置定位间隔,单位毫秒,默认为2000ms
            mLocationOption.setInterval(2000);
            //设置定位参数
            mlocationClient.setLocationOption(mLocationOption);
            // 此方法为每隔固定时间会发起一次定位请求，为了减少电量消耗或网络流量消耗，
            // 注意设置合适的定位时间的间隔（最小间隔支持为2000ms），并且在合适时间调用stopLocation()方法来取消定位请求
            // 在定位结束后，在合适的生命周期调用onDestroy()方法
            // 在单次定位情况下，定位无论成功与否，都无需调用stopLocation()方法移除请求，定位sdk内部会移除
            mlocationClient.startLocation();

        }
    }

    @Override
    public void deactivate() {
        mListener = null;
        if (mlocationClient != null) {
            mlocationClient.stopLocation();
            mlocationClient.onDestroy();
        }
        mlocationClient = null;
    }

    public void removeMarker(int key) {
        if (markers == null || markers.size() == 0)
            return;

        if (markers.get(key) != null) {
            markers.get(key).remove();
            markers.remove(key);
        }
    }

    public void removeAllmarkers() {
        if (markers == null || markers.size() == 0)
            return;

        for (int i = 0; i < markers.size(); i++) {
            markers.valueAt(i).remove();
            markers.removeAt(i);
            i--;
        }
    }

    public void animateCamera(LatLngBounds.Builder boundsBuilder) {
        if (aMap == null) {
            return;
        }
        aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 20));
    }

    public void Destroy() {
        onDestroy();
        if (null != mlocationClient) {
            mlocationClient.onDestroy();
        }
    }

    public void reLocation() {
        if (mlocationClient != null) {
            mlocationClient.stopLocation();
            mlocationClient.startLocation();
        }
    }
}
